﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="Range.cs" company="Joshua Tauberer's">
//   Joshua Tauberer's
// </copyright>
// <summary>
//   The diff. http://razor.occams.info/code/diff/diff/html/index.html
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace Algorithm.Diff
{
    using System;
    using System.Collections;

    /// <summary>
    /// The range.
    /// </summary>
    public class Range : ICollection, IEnumerable
    {
        /// <summary>
        /// The count.
        /// </summary>
        private readonly int count;

        /// <summary>
        /// The list.
        /// </summary>
        private readonly IList list;

        /// <summary>
        /// The start.
        /// </summary>
        private readonly int start;

        /// <summary>
        /// Initializes a new instance of the <see cref="Range"/> class.
        /// </summary>
        /// <param name="list">
        /// The list.
        /// </param>
        /// <param name="start">
        /// The start.
        /// </param>
        /// <param name="count">
        /// The count.
        /// </param>
        public Range(IList list, int start, int count)
        {
            this.list = list;
            this.start = start;
            this.count = count;
        }

        /// <summary>
        /// The check.
        /// </summary>
        /// <exception cref="InvalidOperationException">
        /// </exception>
        private void Check()
        {
            if (this.list == null)
            {
                throw new InvalidOperationException("This range does not refer to a list with data.");
            }
        }

        /// <summary>
        /// The copy to.
        /// </summary>
        /// <param name="array">
        /// The array.
        /// </param>
        /// <param name="index">
        /// The index.
        /// </param>
        void ICollection.CopyTo(Array array, int index)
        {
            this.Check();
            for (int i = 0; i < this.Count; i++)
            {
                array.SetValue(this[i], (int) (i + index));
            }
        }

        /// <summary>
        /// The get enumerator.
        /// </summary>
        /// <returns>
        /// </returns>
        IEnumerator IEnumerable.GetEnumerator()
        {
            this.Check();
            return new Enumer(this);
        }

        /// <summary>
        /// Gets Count.
        /// </summary>
        public int Count
        {
            get
            {
                return this.count;
            }
        }

        /// <summary>
        /// Gets End.
        /// </summary>
        public int End
        {
            get
            {
                return (this.start + this.count) - 1;
            }
        }

        /// <summary>
        /// The this.
        /// </summary>
        /// <param name="index">
        /// The index.
        /// </param>
        /// <exception cref="ArgumentException">
        /// </exception>
        public object this[int index]
        {
            get
            {
                this.Check();
                if ((index < 0) || (index >= this.count))
                {
                    throw new ArgumentException("index");
                }

                return this.list[index + this.start];
            }
        }

        /// <summary>
        /// Gets Start.
        /// </summary>
        public int Start
        {
            get
            {
                return this.start;
            }
        }

        /// <summary>
        /// Gets a value indicating whether IsSynchronized.
        /// </summary>
        bool ICollection.IsSynchronized
        {
            get
            {
                return false;
            }
        }

        /// <summary>
        /// Gets SyncRoot.
        /// </summary>
        object ICollection.SyncRoot
        {
            get
            {
                return null;
            }
        }

        /// <summary>
        /// The enumer.
        /// </summary>
        private class Enumer : IEnumerator
        {
            /// <summary>
            /// The index.
            /// </summary>
            private int index = -1;

            /// <summary>
            /// The list.
            /// </summary>
            private readonly Range list;

            /// <summary>
            /// Initializes a new instance of the <see cref="Enumer"/> class.
            /// </summary>
            /// <param name="list">
            /// The list.
            /// </param>
            public Enumer(Range list)
            {
                this.list = list;
            }

            /// <summary>
            /// The move next.
            /// </summary>
            /// <returns>
            /// The move next.
            /// </returns>
            public bool MoveNext()
            {
                this.index++;
                return this.index < this.list.Count;
            }

            /// <summary>
            /// The reset.
            /// </summary>
            public void Reset()
            {
                this.index = -1;
            }

            /// <summary>
            /// Gets Current.
            /// </summary>
            public object Current
            {
                get
                {
                    return this.list[this.index];
                }
            }
        }
    }
}

